package com.example.demo.handler;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.example.demo.repository.NotificationConfigRepository;
import com.example.demo.entity.NotificationConfig;
import com.example.demo.command.NotificationConfigCommand;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;

@Slf4j
@Component
public class MessageHandler {

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    private final NotificationConfigRepository notificationConfigRepository;
    private final NotificationConfigCommand notificationConfigCommand;
    private static final String MESSAGE_API = "https://www.kookapp.cn/api/v3/message/create";
    private static final String HITOKOTO_API = "https://v1.hitokoto.cn";
    private static final String HELP_MESSAGE = "可用命令：\n" +
            "/ping - 测试机器人是否在线\n" +
            "/echo <内容> - 复读你的消息\n" +
            "/help - 显示此帮助信息\n" +
            "/setnotify <类型> - 设置当前频道为指定类型的通知接收频道\n" +
            "  可用类型：\n" +
            "  voice - 语音频道通知\n" +
            "  text - 文字频道通知\n" +
            "  all - 所有频道通知";
    private static final String NOTIFY_USAGE = "请使用正确的命令格式：/setnotify <类型>\n可用类型：\nvoice - 语音频道通知\ntext - 文字频道通知\nall - 所有频道通知";

    @Autowired
    public MessageHandler(NotificationConfigRepository notificationConfigRepository,
                         NotificationConfigCommand notificationConfigCommand) {
        this.restTemplate = new RestTemplate();
        this.objectMapper = new ObjectMapper();
        this.notificationConfigRepository = notificationConfigRepository;
        this.notificationConfigCommand = notificationConfigCommand;
    }

    private static final String USER_API = "https://www.kookapp.cn/api/v3/user/view";
    private static final String CHANNEL_API = "https://www.kookapp.cn/api/v3/channel/view";
    private static final java.text.SimpleDateFormat DATE_FORMAT = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private HttpEntity<?> createAuthHeader(String token) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bot " + token);
        return new HttpEntity<>(headers);
    }

    private String getUserName(String userId, String token) {
        try {
            ResponseEntity<String> response = restTemplate.exchange(
                USER_API + "?user_id=" + userId,
                org.springframework.http.HttpMethod.GET,
                createAuthHeader(token),
                String.class
            );
            JsonNode userInfo = objectMapper.readTree(response.getBody());
            return userInfo.get("data").get("username").asText();
        } catch (Exception e) {
            log.warn("获取用户信息失败：{}", e.getMessage());
            return "未知用户(" + userId + ")";
        }
    }

    private String getChannelName(String channelId, String token) {
        try {
            ResponseEntity<String> response = restTemplate.exchange(
                CHANNEL_API + "?target_id=" + channelId,
                org.springframework.http.HttpMethod.GET,
                createAuthHeader(token),
                String.class
            );
            JsonNode channelInfo = objectMapper.readTree(response.getBody());
            return channelInfo.get("data").get("name").asText();
        } catch (Exception e) {
            log.warn("获取频道信息失败：{}", e.getMessage());
            return "未知频道(" + channelId + ")";
        }
    }

    private void handleChannelEvent(JsonNode message, String token, String channelType) {
        try {
            JsonNode extraNode = message.get("extra");
            if (extraNode == null) {
                log.warn("消息缺少extra字段：{}", message);
                return;
            }

            JsonNode bodyNode = extraNode.get("body");
            if (bodyNode == null) {
                log.warn("消息缺少body字段：{}", message);
                return;
            }

            // 检查事件类型
            String eventType = extraNode.get("type").asText();
            boolean isJoinEvent = "joined_channel".equals(eventType);
            boolean isExitEvent = "exited_channel".equals(eventType);
            if (!isJoinEvent && !isExitEvent) {
                log.debug("不是频道进出事件，忽略处理：{}", eventType);
                return;
            }

            JsonNode userIdNode = bodyNode.get("user_id");
            JsonNode channelIdNode = bodyNode.get("channel_id");
            if (userIdNode == null || channelIdNode == null) {
                log.warn("消息缺少user_id或channel_id字段：{}", message);
                return;
            }

            String userId = userIdNode.asText();
            String channelId = channelIdNode.asText();
            JsonNode guildIdNode = message.get("target_id");
            if (guildIdNode == null) {
                log.warn("消息缺少target_id字段：{}", message);
                return;
            }
            String guildId = guildIdNode.asText();
            log.info("查询服务器[{}]的通知配置", guildId);

            String userName = getUserName(userId, token);
            String channelName = getChannelName(channelId, token);

            String action = isJoinEvent ? "加入了" : "退出了";
            String channelTypeText;
            switch (channelType) {
                case "1":
                    channelTypeText = "文字频道";
                    break;
                case "2":
                    channelTypeText = "语音频道";
                    break;
                default:
                    channelTypeText = "频道";
            }
            String currentTime = DATE_FORMAT.format(new java.util.Date());
            log.info("用户 [{}] 于 {} {}{} [{}]", userName, currentTime, action, channelTypeText, channelName);

            // 查询配置的通知频道
            List<NotificationConfig> configs = notificationConfigRepository
                .findByGuildIdAndEventTypeAndEnabled(guildId, isJoinEvent ? "channel_join_notify" : "channel_exit_notify", true);
            log.info("找到{}个通知配置", configs.size());

            if (configs.isEmpty()) {
                log.info("服务器[{}]没有配置通知频道", guildId);
                return;
            }

            for (NotificationConfig config : configs) {
                String notifyMessage = String.format("%s 于 %s %s%s %s", userName, currentTime, action, channelTypeText, channelName);
                log.info("发送通知到频道[{}]：{}", config.getChannelId(), notifyMessage);
                sendMessage(config.getChannelId(), notifyMessage, token, null);
            }
        } catch (Exception e) {
            log.error("处理频道事件时出现问题", e);
        }
    }

    public void handleTextMessage(JsonNode message, String token) {
        log.debug("收到消息：{}", message);
        // 检查事件类型
        if (message.has("type") && message.get("type").asInt() == 255 && 
            message.has("extra") && message.get("extra").has("type")) {
            String eventType = message.get("extra").get("type").asText();
            log.info("处理系统事件：{}", eventType);
            
            JsonNode extraNode = message.get("extra");
            if (extraNode == null) {
                log.warn("消息缺少extra字段：{}", message);
                return;
            }

            JsonNode bodyNode = extraNode.get("body");
            if (bodyNode == null) {
                log.warn("消息缺少body字段：{}", message);
                return;
            }

            // 处理用户加入服务器事件
            if ("joined_guild".equals(eventType)) {
                log.info("检测到用户加入服务器事件");
                handleNewUserJoined(message, token);
                return;
            }

            // 处理频道事件
            JsonNode channelTypeNode = bodyNode.get("channel_type");
            String channelType = channelTypeNode != null ? channelTypeNode.asText() : "unknown";
            log.info("收到事件，频道类型：{}", channelType);
            handleChannelEvent(message, token, channelType);
            return;
        }

        try {
            JsonNode extraNode = message.get("extra");
            if (extraNode == null) {
                log.warn("消息缺少extra字段：{}", message);
                return;
            }

            String authorName;
            JsonNode authorNode = extraNode.get("author");
            if (authorNode != null && authorNode.get("username") != null) {
                authorName = authorNode.get("username").asText();
            } else {
                // 尝试从body中获取用户ID
                JsonNode bodyNode = extraNode.get("body");
                if (bodyNode != null && bodyNode.has("user_id")) {
                    String userId = bodyNode.get("user_id").asText();
                    authorName = getUserName(userId, token);
                } else {
                    authorName = "未知用户";
                }
            }
            String channelName = extraNode.get("channel_name") != null ? 
                extraNode.get("channel_name").asText() : "未知频道";
            JsonNode contentNode = message.get("content");
            JsonNode targetIdNode = message.get("target_id");
            
            if (contentNode == null || targetIdNode == null) {
                log.warn("消息缺少content或target_id字段：{}", message);
                return;
            }

            String content = contentNode.asText();
            String channelId = targetIdNode.asText();
            
            log.info("在频道 [{}] 收到来自 [{}] 的消息: {}", channelName, authorName, content);

            // 简单的消息回复逻辑
            if (content.equals("/ping")) {
                log.info("用户 [{}] 发送了ping命令", authorName);
                sendMessage(channelId, "pong!", token, message);
            } else if (content.startsWith("/echo ")) {
                log.info("用户 [{}] 发送了echo命令，内容: {}", authorName, content.substring(6));
                String echoContent = content.substring(6);
                sendMessage(channelId, echoContent, token, message);
            } else if (content.equals("/help")) {
                log.info("用户 [{}] 请求帮助信息", authorName);
                String helpMessage = HELP_MESSAGE;
                sendMessage(channelId, helpMessage, token, message);
            } else if (content.startsWith("/setnotify ")) {
                String[] parts = content.split(" ");
                if (parts.length != 2) {
                    sendMessage(channelId, NOTIFY_USAGE, token, message);
                    return;
                }

                String type = parts[1].toLowerCase();
                String displayType;
                switch (type) {
                    case "voice":
                        displayType = "语音频道";
                        break;
                    case "text":
                        displayType = "文字频道";
                        break;
                    case "all":
                        displayType = "所有频道";
                        break;
                    default:
                        sendMessage(channelId, NOTIFY_USAGE, token, message);
                        return;
                }

                log.info("用户 [{}] 设置{}通知", authorName, displayType);
                JsonNode guildIdNode = message.get("target_id");
                if (guildIdNode == null) {
                    log.warn("消息缺少target_id字段：{}", message);
                    return;
                }
                String guildId = guildIdNode.asText();
                String response = notificationConfigCommand.handleSetNotificationChannel(
                    guildId, channelId, "channel_join_notify");
                sendMessage(channelId, response, token, message);
            }

        } catch (Exception e) {
            log.error("机器人处理消息时出现问题", e);
        }
    }

    private void handleNewUserJoined(JsonNode message, String token) {
        try {
            String channelId = message.get("target_id").asText();
            String newUserName = message.get("extra").get("body").get("user").get("username").asText();
            log.info("新用户 [{}] 加入了服务器", newUserName);

            // 调用一言API获取欢迎语
            ResponseEntity<String> hitokotoResponse = restTemplate.getForEntity(HITOKOTO_API, String.class);
            JsonNode hitokoto = objectMapper.readTree(hitokotoResponse.getBody());
            String welcomeMessage = String.format("欢迎 %s 加入我们！\n这里分享一句话：\n%s", 
                newUserName, hitokoto.get("hitokoto").asText());

            sendMessage(channelId, welcomeMessage, token, message);
        } catch (Exception e) {
            log.error("处理新用户加入事件时出现问题", e);
        }
    }

    private HttpEntity<String> createMessageRequest(String channelId, String content, String token, JsonNode originalMessage) throws Exception {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bot " + token);
        headers.set("Content-Type", "application/json");

        var requestMap = new HashMap<String, Object>();
        requestMap.put("target_id", channelId);
        requestMap.put("content", content);
        if (originalMessage != null && originalMessage.has("msg_id")) {
            requestMap.put("quote", originalMessage.get("msg_id").asText());
        }
        return new HttpEntity<>(objectMapper.writeValueAsString(requestMap), headers);
    }

    private void sendMessage(String channelId, String content, String token, JsonNode originalMessage) {
        try {
            HttpEntity<String> request = createMessageRequest(channelId, content, token, originalMessage);

            log.info("准备发送消息 - 目标频道: {}, 消息内容: {}", channelId, content);
            ResponseEntity<String> response = restTemplate.postForEntity(MESSAGE_API, request, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                JsonNode responseBody = objectMapper.readTree(response.getBody());
                log.debug("responseBody={}", responseBody);
                String msgId = responseBody.get("data").get("msg_id").asText();
                log.info("机器人成功发送消息 - 目标频道: {}, 消息ID: {}", channelId, msgId);
            } else {
                log.error("机器人发送消息失败，目标频道: {}, 服务器返回错误: {}", channelId, response.getBody());
            }
        } catch (Exception e) {
            log.error("机器人发送消息时遇到问题", e);
        }
    }
}